iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
自我挑戰組

JS 加強筆記系列 第 28

Day 28:macrotask 與 microtask (1)

  • 分享至 

  • xImage
  •  

關於 macrotask 和 microtask 有很多文章文件,可以無限延伸深入。這裡只能先作簡單整理,至少有個大方向,以後再慢慢增補。

macrotask

在瀏覽器這個執行環境裡,除了 JS 引擎,還有 Web API、event loop...等等其他部分。Web API 提供了一些好用的功能,例如 setTimeout,或是網路請求 api。在執行這些要花時間的任務 (task/ macrotask) 時,為了不要把主執行環境卡住,瀏覽器會把非同步函式放進 task queue (它還有 event queue, callback queue...等其他 7749 種稱呼),等待 call stack 空了的時候執行。

常見的 macotask:解析 HTML、操控 DOM、使用者事件 (滑鼠、鍵盤...)、載入 script、網路請求、計時器。

microtask

microtask 來自 JS 程式碼本身,通常由 promise 產生。不管 promise 多快或何時 resolve,promise 的 .then/catch/finally 一定都是非同步進行,也就是當 promise 有結果後,這些處理函式的內容會被放進 microtask queue,一樣等到執行堆疊清空後執行。

event loop

event loop 可以想成一段不斷運行的程式,隨時檢查 call stack 和上述兩個 queue 的狀態,並按照順序執行任務。換句話說 event loop 協調不同任務間的執行順序,讓程式不會塞車 (並最終達成非同步的效果)。

執行環境示意圖:
https://ithelp.ithome.com.tw/upload/images/20231013/20141051EHObqT6Gkr.png
source:https://www.datainfinities.com/10/event-loop-and-callback-queue-in-javascript

執行順序

把非同步任務移去 queue 裡排隊這部分不難想像,困擾的是當同時有 macrotask 又有 microtask,它們之間又是以什麼順序執行?

先上一張圖:
https://ithelp.ithome.com.tw/upload/images/20231013/20141051PBqR41hDrw.png
source:這篇的問答區

以圖來說大致可以整理成在每一次 event loop 循環 (迭代) 中:

  1. 在執行完一個 macrotask 之後 (且執行堆疊為空時),會去檢查 microtask queue 是否有任務。
  2. 如果有,則執行所有的 microtask,直到 microtask queue 為空。過程中如果有再產生新的 microtask 也會一起做完。
  3. 如果有需要,重新渲染頁面。
  4. 檢查 macrotask queue,有任務就回到 1. 就開始下一輪循環,沒有則等待。

這個過程中有幾個特點:

  • 每次循環只執行一個 macrotask,也就是如果循環中產生新的 macrotask,必定會在該次循環結束之後才進行。
  • 執行 microtask 的過程中不會處理網頁事件或渲染,這樣確保所有的 microtask 會在同樣的環境執行。
  • 執行任務的過程中不會渲染網頁。

用以上步驟看了一些程式碼然後就立刻翻船了,明天來寫。

參考資料:
https://ithelp.ithome.com.tw/articles/10221944
https://ithelp.ithome.com.tw/articles/10222737
https://www.linkedin.com/pulse/unraveling-javascript-event-loop-comprehensive-guide-michael-baker
https://slawinski.dev/blog/javascript-runtime-environment-web-api-task-queue-and-event-loop/
https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth
https://medium.com/@jain8siddharth8/the-javascript-event-loop-microtasks-and-macrotasks-7db6d918bc03


上一篇
Day 27:如何中斷 forEach
下一篇
Day 29:macrotask 與 microtask (2)
系列文
JS 加強筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言